home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Editors / Emacs / Source / display.pswm < prev    next >
Encoding:
Text File  |  1992-11-30  |  12.2 KB  |  544 lines

  1. /* Postscript code for terminal emulator.
  2.  
  3.    For legal stuff see the file COPYRIGHT.  */
  4.  
  5. #import <appkit/Application.h>
  6. #import <appkit/Pasteboard.h>
  7. #import <appkit/publicWraps.h>
  8. #import <libc.h>
  9. #import <stdlib.h>
  10.  
  11. #import "EtermView.h"
  12.  
  13. /* 2.0 doesn't do transparency in windows correctly.  */
  14. #define TRANSPARENCYBUG
  15.  
  16. #define NORMAL 0
  17. #define PREFIX 1
  18. #define SECOND_PREFIX 2
  19. #define ESCAPE 3
  20. #define STRING 4
  21. #define STRING_FUNCTION 5
  22. #define Ctl(a) ((a) & 0x1f)
  23.  
  24. struct display
  25. {
  26.   EtermView *view;
  27.   int cursor_x, cursor_y;
  28.   int state;
  29.   int insert_mode, standout_mode;
  30.   int prefix, second_prefix;
  31.   char *string_buffer;
  32.   int string_buffer_len;
  33.   int string_char;
  34. };
  35.  
  36. /* Create the information necessary for handling a new display.  The return
  37.    value is the "rock" that should be given to DPSAddFD () as the value to
  38.    give to input_from_emacs ()
  39.  
  40.    (A "rock" is the CMU term for an item you hide information underneath.)  */
  41. void *
  42. new_display_rock (EtermView *view)
  43. {
  44.   struct display *new_display;
  45.  
  46.   new_display = malloc (sizeof (struct display));
  47.   if (!new_display)
  48.     {
  49.       fprintf (stderr, "Emacs: Virtual memory exhausted\n");
  50.       exit (1);
  51.     }
  52.  
  53.   new_display->view = view;
  54.   new_display->cursor_x = new_display->cursor_y = 0;
  55.   new_display->state = NORMAL;
  56.   new_display->prefix = new_display->second_prefix = 0;
  57.   new_display->string_buffer_len = 1024;
  58.   new_display->string_buffer = malloc(1024);
  59.   if (!new_display->string_buffer)
  60.     {
  61.       fprintf (stderr, "Emacs: Virtual memory exhausted\n");
  62.       exit (1);
  63.     }
  64.   new_display->string_char = 0;
  65.  
  66.   return (void *) new_display;
  67. }
  68.  
  69. defineps static setup()
  70. 0 setgray
  71. emacs:fixedfont setfont
  72. endps
  73.  
  74. #ifdef TRANSPARENCYBUG
  75. #define white_rect(x, y, w, h) clear_rect(x, y, w, h)
  76.  
  77. defineps static clear_rect(int x, y, w, h)
  78. 1 setgray
  79. x y w h rectfill
  80. 0 setgray
  81. endps
  82.  
  83. defineps static grey_rect(int x, y, w, h)
  84. 0.6666 setgray
  85. x y w h rectfill
  86. 0 setgray
  87. endps
  88.  
  89. defineps static show_cursor(int x, y, w, h)
  90. x y w h Highlight compositerect
  91. endps
  92.  
  93. #else /* TRANSPARENCYBUG */
  94.  
  95. defineps static white_rect(int x, y, w, h)
  96. 1 setgray
  97. x y w h rectfill
  98. 0 setgray
  99. endps
  100.  
  101. defineps static clear_rect(int x, y, w, h)
  102. x y w h Clear compositerect
  103. endps
  104.  
  105. defineps static grey_rect(int x, y, w, h)
  106. 0.333 setalpha
  107. x y w h rectfill
  108. 1 setalpha
  109. endps
  110.  
  111. defineps static show_cursor(int x, y, w, h)
  112. x y w h Xor compositerect
  113. endps
  114.  
  115. #endif /* TRANSPARENCY_BUG */
  116.  
  117. defineps static copy_rect(int sx, sy, dx, dy, w, h)
  118. sx sy w h gstate dx dy Copy composite
  119. endps
  120.  
  121. defineps static draw_string(int x, y; char s[n]; int n)
  122. x y moveto
  123. (s) show
  124. endps
  125.  
  126. defineps obscure_cursor()
  127. obscurecursor
  128. endps
  129.  
  130. defineps fix_font(int width)
  131. currentfont dup dup
  132. dup /FontMatrix get 0 get 1 exch div width mul /newwidth exch def
  133. length 1 add dict /newfntdict exch def
  134.  { 1 index /FID ne
  135.   {newfntdict 3 1 roll put}
  136.   {pop pop}
  137.  ifelse
  138.  } forall
  139. /CharStrings get
  140. dup length dict exch
  141.  { pop 1 index exch newwidth put }
  142.  forall
  143. newfntdict /Metrics 3 -1 roll put
  144. /emacs:fixedfont /fixedfont newfntdict definefont def
  145. endps
  146.  
  147. defineps set_font()
  148. /emacs:fixedfont currentfont def
  149. endps
  150.  
  151. static void
  152. invalid ()
  153. {
  154. #ifdef DEBUG
  155.   abort();
  156. #endif
  157. }
  158.  
  159. #define POS_X(a) (SIZE_X (a) + BORDER_WIDTH)
  160. #define POS_Y(a) (SIZE_Y (a) + BORDER_WIDTH)
  161. #define SIZE_X(a) ((int) ((a) * fontWidth))
  162. #define SIZE_Y(a) ((int) ((a) * fontHeight))
  163.  
  164. void
  165. input_from_emacs (int fd, void *rock)
  166. {
  167.   struct display *display = (struct display *) rock;
  168.   int screen_x, screen_y;
  169.   int fontHeight, fontWidth;
  170.   int fontDescender;
  171.   char buf[1024+1];
  172.   int n;
  173.   register char c;
  174.   EtermView *view = display->view;
  175.   int cursor_x = display->cursor_x, cursor_y = display->cursor_y;
  176.   int state = display->state;
  177.   int insert_mode = display->insert_mode;
  178.   int standout_mode = display->standout_mode;
  179.   int prefix = display->prefix, second_prefix = display->second_prefix;
  180.   int string_buffer_len = display->string_buffer_len;
  181.   int string_char = display->string_char;
  182.   int x;
  183.  
  184.   n = read(fd, buf, sizeof (buf) - 1);
  185.   if (n < 1)
  186.     {
  187.       [NXApp terminate: nil];
  188.     }
  189.  
  190.   [view lockFocus];
  191.   [view getDimensions: &screen_y : &screen_x];
  192.   [view getDisplayFont: &fontHeight : &fontWidth : &fontDescender];
  193.  
  194.   setup ();
  195.  
  196.   /* Remove old cursor */
  197.   show_cursor(POS_X (cursor_x), POS_Y (cursor_y), fontWidth, fontHeight);
  198.  
  199.   for (x = 0; x < n; x++)
  200.     {
  201.       if ((c = buf[x]) == '\0' && state != STRING)
  202.     continue;
  203.       switch (state)
  204.     {
  205.     case NORMAL:
  206.       if (c >= ' ')
  207.         {
  208.           /* So we print deletes.  Big deal.  */
  209.           int start = x;
  210.           int count;
  211.           int do_newline;
  212.  
  213.           while (++x < n && buf[x] >= ' ');
  214.  
  215.           while (count = x - start)
  216.         {
  217.           if (do_newline = (count + cursor_x >= screen_x))
  218.             count = screen_x - cursor_x;
  219.  
  220.           if (insert_mode)
  221.             {
  222.               copy_rect (POS_X (cursor_x), POS_Y (cursor_y),
  223.                  POS_X (cursor_x + count), POS_Y (cursor_y),
  224.                  SIZE_X (screen_x - cursor_x - count),
  225.                  SIZE_Y (1));
  226.             }
  227.           clear_rect (POS_X (cursor_x), POS_Y (cursor_y),
  228.                   SIZE_X (count), SIZE_Y (1));
  229.  
  230.           if (standout_mode)
  231.             grey_rect (POS_X (cursor_x), POS_Y (cursor_y),
  232.                    SIZE_X (count), SIZE_Y (1));
  233.  
  234.           draw_string (POS_X (cursor_x),
  235.                    POS_Y (cursor_y+1) - (int) fontDescender,
  236.                    &buf[start], count);
  237.  
  238.           start += count;
  239.           if (do_newline)
  240.             {
  241.               cursor_x = 0;
  242.               cursor_y++;
  243.             }
  244.           else
  245.             cursor_x += count;
  246.         }
  247.           --x;
  248.           break;
  249.         }
  250.       switch (c)
  251.         {
  252.         case Ctl ('a'):
  253.         case Ctl ('m'):
  254.           /* Emacs outputs a '\r' on exiting --jgm */
  255.           cursor_x = 0;
  256.           break;
  257.         case Ctl ('b'):
  258.           if (cursor_x > 0)
  259.         --cursor_x;
  260.           break;
  261. #if 0
  262.         case Ctl ('c'):
  263.           do_paste (0);
  264.           break;
  265.         case Ctl ('e'):
  266.           if (EventChannel != -1)
  267.         transmitting_events = TRUE;
  268.           break;
  269. #endif
  270.         case Ctl ('f'):
  271.           if (++cursor_x >= screen_x)
  272.         cursor_x = 0;
  273.           break;
  274.         case Ctl ('g'):
  275.           NXBeep ();
  276.           break;
  277. #if 0
  278.         case Ctl ('h'):
  279.           if (cursor_x > 0)
  280.         {
  281.           --cursor_x;
  282.           delete_chars (1);
  283.         }
  284.           break;
  285. #endif
  286.         case Ctl ('i'):
  287.           insert_mode = !insert_mode;
  288.           break;
  289.         case Ctl ('j'):
  290.           cursor_x = 0;
  291.           cursor_y++;
  292.           break;
  293.         case Ctl ('k'):
  294.           /* clear_to_end_of_line (); */
  295.           clear_rect (POS_X (cursor_x), POS_Y (cursor_y),
  296.               SIZE_X (screen_x - cursor_x), SIZE_Y (1));
  297.           break;
  298. #if 0
  299.         case Ctl ('l'):
  300.           do_redraw ();
  301.           break;
  302. #endif
  303.         case Ctl ('n'):
  304.           if (cursor_y < screen_y)
  305.         cursor_y++;
  306.           break;
  307.         case Ctl ('p'):
  308.           if (cursor_y > 0)
  309.         --cursor_y;
  310.           break;
  311.         case Ctl ('q'):
  312.           state = STRING;
  313.           string_char = 0;
  314.           break;
  315.         case Ctl ('s'):
  316.           standout_mode = !standout_mode;
  317.           break;
  318.         case Ctl ('u'):
  319.           prefix = 0;
  320.           state = PREFIX;
  321.           break;
  322. #if 0
  323.         case Ctl ('y'):
  324.           wm_GiveupInputFocus();
  325.           break;
  326.         case Ctl ('z'):
  327.           [NXApp hide:view];
  328.           break;
  329. #endif
  330.         case Ctl ('['):
  331.           state = ESCAPE;
  332.           break;
  333.         case Ctl ('t'):
  334.           /* Not implemented yet. Besides, no one will ever use it.  */
  335.         default:
  336.           invalid ();
  337.           break;
  338.         }
  339.       break;
  340.     case PREFIX:
  341.       switch (c)
  342.         {
  343.         case '0': case '1': case '2': case '3': case '4':
  344.         case '5': case '6': case '7': case '8': case '9':
  345.           prefix = prefix * 10 + c - '0';
  346.           break;
  347.         case '-':
  348.           prefix = -prefix;
  349.           break;
  350. #if 0
  351.         case Ctl ('a'):
  352.           transmitting_events = FALSE;
  353.           close (EventChannel);
  354.           EventChannel = -1;
  355.           goto normal_state;
  356.         case Ctl ('c'):
  357.           do_paste (prefix);
  358.           goto normal_state;
  359. #endif
  360.         case Ctl ('d'):
  361.           if (prefix > 0)
  362.         {
  363.           /* Delete_chars (prefix); */
  364.           copy_rect (POS_X (cursor_x + prefix), POS_Y (cursor_y),
  365.                  POS_X (cursor_x), POS_Y (cursor_y),
  366.                  SIZE_X (screen_x - cursor_x - 1), SIZE_Y (1));
  367.           clear_rect (POS_X (screen_x - prefix), POS_Y (cursor_y),
  368.                   SIZE_X (prefix), SIZE_Y (1));
  369.         }
  370.           goto normal_state;
  371. #if 0
  372.         case Ctl ('e'):
  373.           transmitting_events = FALSE;
  374.           goto normal_state;
  375. #endif
  376.         case Ctl ('k'):
  377.           if (prefix > 0)
  378.         {
  379.           /* Delete_lines (prefix); */
  380.           copy_rect (POS_X (0), POS_Y (cursor_y + prefix),
  381.                  POS_X (0), POS_Y (cursor_y),
  382.                  SIZE_X (screen_x),
  383.                  SIZE_Y (screen_y - cursor_y - prefix));
  384.           clear_rect (POS_X (0), POS_Y (screen_y - prefix),
  385.                   SIZE_X (screen_x), SIZE_Y (prefix));
  386.         }
  387.           goto normal_state;
  388.         case Ctl ('o'):
  389.           if (prefix > 0)
  390.         {
  391.           /* Insert_lines (prefix); */
  392.           copy_rect (POS_X (0), POS_Y (cursor_y),
  393.                  POS_X (0), POS_Y (cursor_y + prefix),
  394.                  SIZE_X (screen_x),
  395.                  SIZE_Y (screen_y - cursor_y - prefix));
  396.           clear_rect (POS_X (0), POS_Y (cursor_y),
  397.                   SIZE_X (screen_x), SIZE_Y (prefix));
  398.         }
  399.           goto normal_state;
  400.         case Ctl ('q'):
  401.           state = STRING;
  402.           string_char = 0;
  403.           break;
  404.         case Ctl ('u'):
  405.           second_prefix = 0;
  406.           state = SECOND_PREFIX;
  407.           break;
  408.         case '_':
  409.           /* Insert_spaces (prefix); */
  410.           if (prefix > 0)
  411.         {
  412.           copy_rect (POS_X (cursor_x), POS_Y (cursor_y),
  413.                  POS_X (cursor_x + prefix), POS_Y (cursor_y),
  414.                  SIZE_X (screen_x - cursor_x - prefix),
  415.                  SIZE_Y (1));
  416.           clear_rect (POS_X (cursor_x), POS_Y (cursor_y),
  417.                   SIZE_X (prefix), SIZE_Y (1));
  418.         }
  419.           goto normal_state;
  420.         case '.':
  421.           cursor_x = prefix < screen_x ? prefix : 0;
  422.           goto normal_state;
  423.         default:
  424.           invalid ();
  425.         normal_state:
  426.           state = NORMAL;
  427.           break;
  428.         }
  429.       break;
  430.     case SECOND_PREFIX:
  431.       switch (c)
  432.         {
  433.         case '0': case '1': case '2': case '3': case '4':
  434.         case '5': case '6': case '7': case '8': case '9':
  435.           second_prefix = second_prefix * 10 + c - '0';
  436.           break;
  437.         case '.':
  438.           cursor_x = second_prefix < screen_x ? second_prefix : 0;
  439.           cursor_y = prefix < screen_y ? prefix : 0;
  440.           state = NORMAL;
  441.           break;
  442.         default:
  443.           invalid ();
  444.           state = NORMAL;
  445.           break;
  446.         }
  447.       break;
  448.     case ESCAPE:
  449.       switch (c)
  450.         {
  451.         case 'c':
  452.           /* clear_screen (); */
  453.           white_rect (0, 0, SIZE_X (screen_x) + 2 * BORDER_WIDTH,
  454.               SIZE_Y(screen_y) + 2 * BORDER_WIDTH);
  455. #ifndef TRANSPARENCYBUG
  456.           clear_rect (POS_X (0), POS_Y (0),
  457.               SIZE_X (screen_x), SIZE_Y (screen_y));
  458. #endif
  459.           cursor_x = cursor_y = 0;
  460.           insert_mode = standout_mode = 0;
  461.           break;
  462.         case 'k':
  463.           /* Clear_to_end_of_screen (); */
  464.           clear_rect (POS_X (0), POS_Y (cursor_y),
  465.               SIZE_X (screen_x), SIZE_Y (screen_y - cursor_y));
  466.           break;
  467.         default:
  468.           invalid ();
  469.           break;
  470.         }
  471.       state = NORMAL;
  472.       break;
  473.     case STRING:
  474.       if (string_char == string_buffer_len)
  475.         {
  476.           string_buffer_len += 1024;
  477.           display->string_buffer = realloc(display->string_buffer,
  478.                            string_buffer_len);
  479.           if (!display->string_buffer)
  480.         {
  481.           fprintf (stderr, "Emacs: Virtual memory exhausted\n");
  482.           exit (1);
  483.         }
  484.         }
  485.       if ((display->string_buffer[string_char++] = c) == '\377')
  486.         state = STRING_FUNCTION;
  487.       break;
  488.     case STRING_FUNCTION:
  489.       {
  490.         display->string_buffer[--string_char] = '\0';
  491.         switch (c)
  492.           {
  493.           case 'c':
  494.         [[view pasteboard] declareTypes: &NXAsciiPboardType
  495.                                num: 1
  496.                                    owner: NULL];
  497.         [[view pasteboard] writeType: NXAsciiPboardType
  498.                                data: display->string_buffer
  499.                        length: string_char];
  500.         break;
  501. #if 0
  502.           case 'e':
  503.         write (MasterChannel, display->string_buffer, string_char);
  504.         break;
  505.           case 'f':
  506.         change_font (display->string_buffer);
  507.         do_redraw ();
  508.         break;
  509. #endif
  510.           case 't':
  511.         [view setTitle: display->string_buffer];
  512.         break;
  513. #if 0
  514.           case 'p':
  515.         wm_SetProgramName (display->string_buffer);
  516.         break;
  517.           case 'm':
  518.         wm_AddMenu (display->string_buffer);
  519.         break;
  520. #endif
  521.           default:
  522.         invalid();
  523.         break;
  524.           }
  525.         state = NORMAL;
  526.       }
  527.     }
  528.     }
  529.  
  530.   /* Display cursor */
  531.   show_cursor (POS_X (cursor_x), POS_Y (cursor_y), fontWidth, fontHeight);
  532.  
  533.   [view unlockFocus];
  534.   display->cursor_x = cursor_x;
  535.   display->cursor_y = cursor_y;
  536.   display->state = state;
  537.   display->insert_mode = insert_mode;
  538.   display->standout_mode = standout_mode;
  539.   display->prefix = prefix;
  540.   display->second_prefix = second_prefix;
  541.   display->string_buffer_len = string_buffer_len;
  542.   display->string_char = string_char;
  543. }
  544.